package main

import (
	"log"
	"os"
	"os/exec"
	"runtime"
	"syscall"
	"time"
)

// 根据进程名称关闭已有进程
func killProcessByName(name string) error {
	var cmd *exec.Cmd

	if runtime.GOOS == "windows" {
		// Windows: 使用 taskkill 命令
		cmd = exec.Command("taskkill", "/F", "/IM", name)
	} else {
		// Linux: 使用 pkill 命令
		cmd = exec.Command("pkill", name)
	}

	return cmd.Run()
}

// 重启程序
func restartProgram(name string) {
	// 获取当前程序的路径
	executable, err := os.Executable()
	if err != nil {
		log.Fatalf("无法获取程序路径: %v", err)
	}

	// 关闭已有进程
	err = killProcessByName(name)
	if err != nil {
		log.Printf("无法关闭已有进程: %v", err)
	}

	cmd := exec.Command(executable, os.Args[1:]...)

	// 下面代码Windows 专用
	if runtime.GOOS == "windows" {
		cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
	}

	// 启动新进程
	err = cmd.Start()
	if err != nil {
		log.Fatalf("启动新进程失败: %v", err)
	}
	log.Printf("启动新进程: PID=%d", cmd.Process.Pid)

	// 异常处理，确保程序退出时能正常重启
	go func() {
		if err := cmd.Wait(); err != nil {
			log.Printf("新进程退出: %v", err)
		}
	}()

	// 等待新进程启动稳定
	time.Sleep(1 * time.Second)

	// 确保旧进程正常退出
	os.Exit(0)
}

func main() {
	log.Println("程序启动")

	// 标志变量避免重启循环
	restarted := false

	name := "reload"
	// 模拟程序运行
	for {
		log.Println("程序正在运行...")
		time.Sleep(1 * time.Second) // 模拟任务执行时间

		// 如果未重启，则进行重启
		if !restarted && time.Now().Second()%10 == 0 { // 每30秒重启一次
			log.Println("准备重启程序")
			restartProgram(name)
			restarted = true
		}

		// 一旦重启，程序会退出，所以主循环会在旧进程中继续执行
		if restarted {
			break
		}
	}
}
